package control;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import foundation.SurModel.rndForest.RndForestSurModel;
import foundation.SurModel.rndForest.sample.MLearnTbl;
import foundation.SurModel.rndForest.sample.RelbLearnTblItem;
import foundation.fileUtil.TxtFileUtil;

public class RelbEvaluator {
	protected ExeCtx exeCtx = null;
	protected String basePath = null;
	protected List<StringBuffer> curDfCodes = null;
	protected int curReblSolveNum = 0;// 当前求解性能指标的次数
	protected int curPredReblNum = 0;// 当前预测性能指标的次数
	protected boolean isInPredPhase = false;// 起始时处于解析阶段，而非预测阶段
	protected boolean useMLearn = false;// 否使用机器学习
	protected int sampleNum = 400;// 采样的样本数， 在求解真值状态下，采得样本数超过该值就触发机器学习;
	protected int predictNum = 14 * 30 * 20;// 预测次数，超过该次数需要求解真值
	protected MLearnTbl mlTbl=MLearnTbl.getInstance();//机器学习表
	// 代理模型类
	RndForestSurModel model = RndForestSurModel.getInstance();

	public RelbEvaluator(ExeCtx exeCtx) {
		this.exeCtx = exeCtx;
		basePath = exeCtx.getRunBasePath();
		curDfCodes = exeCtx.getCurFdCodes();
		useMLearn = exeCtx.isUseMLearn();
		sampleNum = exeCtx.getSampleNum();
		predictNum = exeCtx.getPredictNum();
	}

	/**
	 * 解析可靠性
	 */
	protected synchronized void solveRelt() {// 由控制器保障当前SA更新
		// 单例模式获取对象
		SASolver saSolver = exeCtx.getSaSolver();
		// 删除上次解析结果
		//////////////////////////////////
		// 解析可靠性
		saSolver.RunPCMReliability();
	}

	/**
	 * 从评估报告中读取可靠性指标值
	 * @return
	 */
	protected float readReltVal() {
		float reltyVal = 0f;
		try {
			String encoding = "GBK";
			File reltFile = exeCtx.getReltRptFile();
			if (reltFile.isFile() && reltFile.exists()) { // 判断文件是否存在
				InputStreamReader read = new InputStreamReader(new FileInputStream(reltFile), encoding);// 考虑到编码格式
				BufferedReader bufferedReader = new BufferedReader(read);
				String lineTxt = null;
				while ((lineTxt = bufferedReader.readLine()) != null) {
					Pattern p = Pattern.compile(">0(.*)</font>");
					Matcher m = p.matcher(lineTxt);
					while (m.find()) {
						reltyVal = Float.valueOf("0" + m.group(1));
					}
				}
				read.close();
			} else {
				System.out.println("找不到指定的文件");
			}
		} catch (Exception e) {
			System.out.println("读取文件内容出错");
			e.printStackTrace();
		}
		return reltyVal;
	}

	/**
	 * 在预测阶段获取可靠性学习表项
	 * @return
	 */
	private RelbLearnTblItem getReltValInpredPhase() {
		RelbLearnTblItem relbTblItem=new RelbLearnTblItem();
		curPredReblNum++;
		if (curPredReblNum <= predictNum) {//// 通过预测获取可靠性预测值
			List<StringBuffer> mlDfCodes = exeCtx.toMLDfcodes();
			relbTblItem.setMlDFcodes(mlDfCodes);		
			float reltVal=-1f;
			try {
				reltVal = model.predictRelb(mlDfCodes);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			relbTblItem.setPredictRelbVal(reltVal);

		} else {// 下一次转入解析阶段
			isInPredPhase = false;
			curReblSolveNum = 0;
			curPredReblNum = 0;
			relbTblItem = getReltValInSolvePhase();// 进入解析阶段
		}
		return relbTblItem;
	}

	/**
	 * 在解析阶段获取可靠性学习表项
	 * @return
	 */
	private RelbLearnTblItem getReltValInSolvePhase() {
		RelbLearnTblItem relbTblItem=new RelbLearnTblItem();
		curReblSolveNum++;// 次数加1
		if (curReblSolveNum <= sampleNum) {// 样本采集不足
			solveRelt();// 解析
			float reltVal = readReltVal();// 从报告中读取值
			List<StringBuffer> mlDfCodes = exeCtx.toMLDfcodes();
			relbTblItem.setMlDFcodes(mlDfCodes);
			relbTblItem.setActualRelbVal(reltVal);

		} else {// 进入预测阶段
			isInPredPhase = true;
			curReblSolveNum = 0;
			curPredReblNum = 0;
			model.trainRelb();// 启动模型训练，为预测作准备
			relbTblItem = getReltValInpredPhase();// 进入预测阶段
		}
		return relbTblItem;
	}
	/**
	 * 从可靠性学习表项获取指标值
	 * @param relbTblItem:可靠性学习表项
	 * @return
	 */
	protected float getFrm(RelbLearnTblItem relbTblItem){
		float RelbVal=-1f;
		if(Float.compare(relbTblItem.getActualRelbVal(),-1)==0){
			RelbVal=relbTblItem.getPredictRelbVal();
		}
		else{
			RelbVal=relbTblItem.getActualRelbVal();
		}
		return 	RelbVal;
	}
	/**
	 * 获取可靠性值
	 */
	public float getReltVal() {//
		RelbLearnTblItem relbTblItem=new RelbLearnTblItem();
		float reltVal = Float.MAX_VALUE;
//		if (useMLearn) {// 使用机器学习
//			if (isInPredPhase) {// 在预测阶段
//				relbTblItem = getReltValInpredPhase();
//				mlTbl.addRelbItem(relbTblItem);
//				reltVal=getFrm(relbTblItem);
//			}
//			else{//在解析阶段
//				relbTblItem = getReltValInSolvePhase();
//				mlTbl.addRelbItem(relbTblItem);
//				reltVal=getFrm(relbTblItem);
//			}
//		} else {// 不使用机器学习，直接解析
			solveRelt();// 解析
			reltVal = readReltVal();// 从报告中读取值
//		}
		return reltVal;
	}

	public ExeCtx getExeCtx() {
		return exeCtx;
	}

	public void setExeCtx(ExeCtx exeCtx) {
		this.exeCtx = exeCtx;
	}

	public String getBasePath() {
		return basePath;
	}

	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

	public List<StringBuffer> getCurDfCodes() {
		return curDfCodes;
	}

	public void setCurDfCodes(List<StringBuffer> curDfCodes) {
		this.curDfCodes = curDfCodes;
	}

	public int getCurReblSolveNum() {
		return curReblSolveNum;
	}

	public void setCurReblSolveNum(int curReblSolveNum) {
		this.curReblSolveNum = curReblSolveNum;
	}

	public int getCurPredReblNum() {
		return curPredReblNum;
	}

	public void setCurPredReblNum(int curPredReblNum) {
		this.curPredReblNum = curPredReblNum;
	}

	public boolean isInPredPhase() {
		return isInPredPhase;
	}

	public void setInPredPhase(boolean isInPredPhase) {
		this.isInPredPhase = isInPredPhase;
	}

	public boolean isUseMLearn() {
		return useMLearn;
	}

	public void setUseMLearn(boolean useMLearn) {
		this.useMLearn = useMLearn;
	}

	public int getSampleNum() {
		return sampleNum;
	}

	public void setSampleNum(int sampleNum) {
		this.sampleNum = sampleNum;
	}

	public int getPredictNum() {
		return predictNum;
	}

	public void setPredictNum(int predictNum) {
		this.predictNum = predictNum;
	}

	public MLearnTbl getMlTbl() {
		return mlTbl;
	}

	public void setMlTbl(MLearnTbl mlTbl) {
		this.mlTbl = mlTbl;
	}

	public RndForestSurModel getModel() {
		return model;
	}

	public void setModel(RndForestSurModel model) {
		this.model = model;
	}
	
	
}
